﻿namespace NTrace
{
  using System;
  using System.Collections.Generic;

  public class Configuration
  {
    private ConfigurationProviderType providerType;
    private ConfigurationMethodTracing methodTracing;
    private ConfigurationMacros macros;
    private IDictionary<String, byte> traceLevels;
    private IDictionary<String, int> traceFlags;

    public Configuration()
    {
      this.providerType = new ConfigurationProviderType();
      this.methodTracing = new ConfigurationMethodTracing();
      this.macros = new ConfigurationMacros();
      this.traceLevels = new Dictionary<string, byte>();
      this.traceLevels.Add("Fatal", 1);
      this.traceLevels.Add("Error", 2);
      this.traceLevels.Add("Warning", 3);
      this.traceLevels.Add("Information", 4);
      this.traceLevels.Add("Verbose", 5);
      this.traceLevels.Add("Noise", 6);

      this.traceFlags = new Dictionary<string, int>();
      this.traceFlags.Add("Component", 1);
      this.traceFlags.Add("Protocol", 2);
      this.traceFlags.Add("Connection", 4);
      this.traceFlags.Add("Security", 8);
      this.traceFlags.Add("Diagnostic", 16);
      this.traceFlags.Add("Authentication", 32);
      this.traceFlags.Add("Parsing", 64);
      this.traceFlags.Add("Network", 128);
      this.traceFlags.Add("StackTracing", 256);
    }

    /// <remarks/>
    public ConfigurationProviderType ProviderType
    {
      get
      {
        return this.providerType;
      }
      set
      {
        this.providerType = value;
      }
    }

    /// <remarks/>
    public ConfigurationMethodTracing MethodTracing
    {
      get
      {
        return this.methodTracing;
      }
      set
      {
        this.methodTracing = value;
      }
    }

    /// <remarks/>
    public ConfigurationMacros Macros
    {
      get
      {
        return this.macros;
      }
      set
      {
        this.macros = value;
      }
    }

    /// <remarks/>
    public IDictionary<String, byte> TraceLevels
    {
      get
      {
        return this.traceLevels;
      }
      set
      {
        this.traceLevels = value;
      }
    }

    /// <remarks/>
    public IDictionary<String, int> TraceFlags
    {
      get
      {
        return this.traceFlags;
      }
      set
      {
        this.traceFlags = value;
      }
    }

    public static Configuration Load()
    {
      return Configuration.Load(null);
    }

    public static Configuration Load(String configurationFile)
    {
      // TODO - deserialize from XML
      Configuration output = null;
      
      if (String.IsNullOrEmpty(configurationFile))
      {
        output = new Configuration();
      }
      else
      {
        if (!System.IO.File.Exists(configurationFile))
        {
          throw new PreprocessorException(
            PreprocessorErrors.ConfigFileNotFound, 
            String.Format("Configuration file '{0}' not found.", configurationFile)
            );
        }

        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Configuration));

        using (System.IO.FileStream configurationFileStream = new System.IO.FileStream(configurationFile, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
        {
          output = serializer.Deserialize(configurationFileStream) as Configuration;
          if (output == null)
          {
            throw new PreprocessorException(
              PreprocessorErrors.CantLoadConfig,
              String.Format("Unable to load configuration from configuration file '{0}'.", configurationFile)
              );
          }
        }
      }

      return output;
    }
  }

  public class ConfigurationProviderType
  {
    private string namespaceField;
    private string nameField;

    public ConfigurationProviderType()
    {
      this.namespaceField = "NTrace";
      this.nameField = "EtwProvider";
    }

    /// <remarks/>
    public string Namespace
    {
      get
      {
        return this.namespaceField;
      }
      set
      {
        this.namespaceField = value;
      }
    }

    /// <remarks/>
    public string Name
    {
      get
      {
        return this.nameField;
      }
      set
      {
        this.nameField = value;
      }
    }
  }

  public class ConfigurationMethodTracing
  {
    private String levelField = "Noise";
    private String flagField = "StackTracing";
    private String entryMessageField;
    private String exitMessageField;

    public ConfigurationMethodTracing()
    {
      this.entryMessageField = "Enter.";
      this.exitMessageField = "Exit.";
    }

    /// <remarks/>
    public String Level
    {
      get
      {
        return this.levelField;
      }
      set
      {
        this.levelField = value;
      }
    }

    /// <remarks/>
    public String Flag
    {
      get
      {
        return this.flagField;
      }
      set
      {
        this.flagField = value;
      }
    }

    /// <remarks/>
    public String EntryMessage
    {
      get
      {
        return this.entryMessageField;
      }
      set
      {
        this.entryMessageField = value;
      }
    }

    /// <remarks/>
    public String ExitMessage
    {
      get
      {
        return this.exitMessageField;
      }
      set
      {
        this.exitMessageField = value;
      }
    }
  }

  public class ConfigurationMacros
  {
    private string traceField;
    private string traceEnabledField;
    private string traceLevelCheckField;
    private string traceFlagCheckField;
    private string traceFlagLevelCheckField;

    public ConfigurationMacros()
    {
      this.traceField = "Trace";
      this.traceEnabledField = "Enabled";
      this.traceLevelCheckField = "TraceLevelEnabled";
      this.traceFlagCheckField = "TraceFlagEnabled";
      this.traceFlagLevelCheckField = "TraceFlagAndLevelEnabled";
    }

    /// <remarks/>
    public string Trace
    {
      get
      {
        return this.traceField;
      }
      set
      {
        this.traceField = value;
      }
    }

    /// <remarks/>
    public string EnabledCheck
    {
      get
      {
        return this.traceEnabledField;
      }
      set
      {
        this.traceEnabledField = value;
      }
    }

    /// <remarks/>
    public string TraceLevelCheck
    {
      get
      {
        return this.traceLevelCheckField;
      }
      set
      {
        this.traceLevelCheckField = value;
      }
    }

    /// <remarks/>
    public string TraceFlagCheck
    {
      get
      {
        return this.traceFlagCheckField;
      }
      set
      {
        this.traceFlagCheckField = value;
      }
    }

    /// <remarks/>
    public string TraceFlagLevelCheck
    {
      get
      {
        return this.traceFlagLevelCheckField;
      }
      set
      {
        this.traceFlagLevelCheckField = value;
      }
    }
  }
}
